import java.net.*;
import java.io.*;

public
class ChatServerThread extends Thread{

	protected Socket socket;
	protected DataOutputStream out;
	protected BufferedReader in;
	protected ChatServer chatServer;
	protected ThreadsArray threadsArray;

	public String nick = null;
	protected PrintWriter outLog = null;
	private boolean stopped = false;
	private String name;

	public ChatServerThread(Socket socket, PrintWriter outLog, ChatServer chatServer)
	{
		super();
		this.socket = socket;
		this.chatServer = chatServer;
		this.threadsArray = chatServer.threadsArray;
		this.outLog = outLog;
		name = this.getName();
	}
	public void run(){
	try{
		try{
			out = new DataOutputStream(socket.getOutputStream());
		in = new BufferedReader(new InputStreamReader  (socket.getInputStream()));
		}
		catch(IOException e){
			writeLog(name + "Bd przy tworzeniu strumieni: " + e);
			stopped = true;
			return;
		}
		String line;
		while(!stopped){
			try{
				line = in.readLine();
				writeLog(name + "Odebrano lini: " + line);
				if (line == null){
		writeLog(name + "Wtek \"" + this + "\" zosta zatrzymany. Odebrano warto null.");
					return;
				}
				processMessage(line);
			}
			catch(IOException e){
				writeLog(name + "Bd przy odczycie danych: " + e);
				return;
			}
		}
	}
	finally{
		quit();
	}
	}
	public String getInfo()
	{
		String info;
		info = "IP " + socket.getInetAddress().getHostAddress() + " ";
		info += "Port " + socket.getPort() + " ";
		info += name + " nick: " + ((nick != null)?nick:"-");
		return info;
	}
	public void send(String line)
	{
		try{
			out.writeBytes(line + "\n");
			writeLog(name + "Wysano: " + line);
		}
		catch(IOException e){
			writeLog(name + "Bd wejcia-wyjcia: " + e);
			quit();
		}
	}
	public void sendToAll(String line){
		synchronized(threadsArray){
			for (int i = 0; i < threadsArray.size(); i++){
		ChatServerThread serverThread = chatServer.threadsArray.getThread(i);
				if (serverThread.nick != null)
					serverThread.send(line);
			}
		}
	}
	public void processMessage(String line)
	{
		writeLog(name + "Przetwarzam lini: " + line);
		if (line.length() < 5){
			if (nick != null){
				sendToAll(nick + "> " + line);
			}
			else{
				send("/nonk");
			}
			return;
		}
		String command = line.substring(0, 5);
		if (command.equals("/quit")){
			send("/quit");
			stopped = true;
			//quit();
		}
		else if (command.equals("/nick")){
			if (line.length() < 7){
				send("/nonk");
				return;
			}
			String nick = line.substring(6, line.length());
			if (!nickExists(nick)){
				send("/nkok");
				if (this.nick != null){
					sendToAll("/nkrm " + this.nick);
				}
				this.nick = nick;
				sendAllNicks();
				sendToAll("/nick " + nick);
			}
			else{
				send("/nkex");
			}
		}
		else{
			if (nick != null){
				sendToAll(nick + "> " + line);
			}
			else{
				send("/nonk");
			}
		}
	}
	public boolean nickExists(String nick)
	{
		synchronized(threadsArray){
			for (int i = 0; i < threadsArray.size(); i++){
		ChatServerThread serverThread = threadsArray.getThread(i);
		if((serverThread.nick != null) && serverThread.nick.equals(nick)){
			return true;
				}
			}
			return false;
		}
	}
	public void quit(){
		synchronized(threadsArray){
			threadsArray.removeElement(this);
		}
		sendToAll("/nkrm " + this.nick);
		writeLog(name + "Wtek zatrzymany.");
	}
	public void sendAllNicks()
	{
		synchronized(threadsArray){
			for (int i = 0; i < threadsArray.size(); i++){
				String nick = threadsArray.getThread(i).nick;
				if ((nick != null) && !nick.equals(this.nick)){
					send("/nick " + nick);
				}
			}
		}
	}
	public void writeLog(String line)
	{
		chatServer.writeLog(line);
	}
}
